﻿using System;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using MetroDropBox.Shared;
using System.Threading.Tasks;
using System.Collections.Generic;
using MetroEventbrite.Shared;

namespace Eventbrite
{
    public enum EventStatus
    {
        Live, Started, Ended
    }

    public enum SortOrder
    {
        Asc, Desc
    }
    public enum TicketFilterType
    {
         Public, Private, All
    }

    public class EventbriteClient : oAuth2ClientBase
    {
        public EventbriteClient(string apiKey) : base(apiKey) { }

        protected override void init()
        {
            useSha1Signing = true;
            usesAuthHeader = true;
            upperCaseUrlEncoding = true;
            usesOAuthVerifier = true;
            getUserLoginURL = "https://www.eventbrite.com/oauth/authorize?response_type=token&client_id=";

        }
        #region User
        public async Task<String> GetUser(string userKey = "", string userId = "")
        {
            var url = "https://www.eventbrite.com/json/user_get";
            var parms = new Dictionary<string,string>();
            if(!string.IsNullOrEmpty(userKey))
                parms.Add("user_key", userKey);

            if(!string.IsNullOrEmpty(userId))
                parms.Add("user_id", userId);
            
            return await httpGetForString(url, parms);
        }

        public async Task<String> ListUserEvents(string userEmail, string[] doNotDisplay = null, EventStatus[] eventStatuses = null, SortOrder sortOrder = SortOrder.Asc)
        {
            var url = "https://www.eventbrite.com/json/user_list_events";
            var parms = new Dictionary<string,string>();
            if (!string.IsNullOrEmpty(userEmail))
                parms.Add("user", userEmail);
            if (doNotDisplay != null && doNotDisplay.Length > 0)
                parms.Add("do_not_display", String.Join(",", doNotDisplay.Select(i => i.ToString().ToLower()).ToArray()));
            if (eventStatuses != null && eventStatuses.Length > 0)
                parms.Add("event_statuses", String.Join(",", eventStatuses.Select(i=>i.ToString().ToLower()).ToArray()));
            parms.Add("asc_or_desc", sortOrder.ToString().ToLower());
            
            return await httpGetForString(url, parms);
        }
        public async Task<String> ListUserTickets(TicketFilterType type = TicketFilterType.Public)
        {
            var url = "https://www.eventbrite.com/json/user_list_tickets";
            var parms = new Dictionary<string, string>();
            parms.Add("type", type.ToString().ToLower());
            return await httpGetForString(url, parms);
        }
        public async Task<String> ListUserVenues()
        {
            var url = "https://www.eventbrite.com/json/user_list_venues";
            var parms = new Dictionary<string, string>();
            return await httpGetForString(url, parms);
        }
        public async Task<String> ListOrganizersForUser()
        {
            var url = "https://www.eventbrite.com/json/user_list_organizers";
            var parms = new Dictionary<string, string>();
            return await httpGetForString(url, parms);
        }
        public async Task<String> NewUser(string email, string password)
        {
            var url = "https://www.eventbrite.com/json/user_new";
            var parms = new Dictionary<string, string>();
            parms.Add("email", email);
            parms.Add("passwd", password);
            return await httpGetForString(url, parms);
        }
        public async Task<String> UpdateUser(string email, string password)
        {
            var url = "https://www.eventbrite.com/json/user_update";
            var parms = new Dictionary<string, string>();
            parms.Add("new_email", email);
            parms.Add("new_password", password);
            return await httpGetForString(url, parms);
        }
        #endregion

        #region Payments
        public async Task<String> UpdatePayments(
                string eventId, 
                bool acceptPaypal, 
                string paypalEmail, 
                bool acceptGoogle, 
                string googleMerchentId, 
                string googleMerchentKey,
                bool acceptCheck, 
                string checkInstructions,
                bool acceptCash, 
                string cashInstructions,
                bool acceptInvoice,
                string invoiceInstructions)
        {
            var url = "https://www.eventbrite.com/json/payment_update";
            var parms = new Dictionary<string, string>();
            parms.Add("event_id", eventId);
            parms.Add("accept_paypal", acceptPaypal?"0":"1");
            parms.Add("paypal_email", paypalEmail);
            parms.Add("accept_google", acceptGoogle ? "0" : "1");
            parms.Add("google_merchant_id", googleMerchentId);
            parms.Add("google_merchant_key", googleMerchentKey);
            parms.Add("accept_check", acceptCheck ? "0" : "1");
            parms.Add("instructions_check", checkInstructions);
            parms.Add("accept_cash", acceptCash ? "0" : "1");
            parms.Add("instructions_cash", cashInstructions);
            parms.Add("accept_invoice", acceptInvoice ? "0" : "1");
            parms.Add("instructions_invoice", invoiceInstructions);

            return await httpGetForString(url, parms);
        }
        #endregion
        
        #region Organizer
        public async Task<String> GetOrganizersEvents(string organizerId)
        {
            var url = "https://www.eventbrite.com/json/organizer_list_events";
            var parms = new Dictionary<string, string>();
            parms.Add("id", organizerId);

            return await httpGetForString(url, parms);
        }
        public async Task<String> NewOrganizer(string name, string description)
        {
            var url = "https://www.eventbrite.com/json/organizer_new";
            var parms = new Dictionary<string, string>();
            parms.Add("name", name);
            parms.Add("description", description);
            return await httpGetForString(url, parms);
        }
        public async Task<String> UpdateOrganizer(string organizerId, string name, string description)
        {
            var url = "https://www.eventbrite.com/json/organizer_update";
            var parms = new Dictionary<string, string>();
            parms.Add("id", organizerId);
            parms.Add("name", name);
            parms.Add("description", description);
            return await httpGetForString(url, parms);
        }
        
        #endregion

        #region Attendees
        public async Task<String> ListAttendeesForEvent(string eventId, int countPerPage = 50, int pageNum = 1, string[] doNotGetTheseFields = null, bool fullBarcodes = false)
        {
            var url = "https://www.eventbrite.com/json/event_list_attendees";
            var parms = new Dictionary<string, string>();
            parms.Add("id", eventId);
            parms.Add("count", countPerPage.ToString());
            pageNum = pageNum < 0 ? 1 : pageNum;
            parms.Add("page", pageNum.ToString());
            parms.Add("do_not_display", string.Join(",", doNotGetTheseFields.Select(i=>i.Trim())));
            parms.Add("show_full_barcodes", fullBarcodes.ToString().ToLower());

            return await httpGetForString(url, parms);
        }
        #endregion

        #region Tickets        
        public async Task<String> NewTicket(string eventId, string ticketName, string description, float price, int numberOfTickets, DateTime startOfSales, DateTime endOfSales, bool freeEventWithDonation = false, bool showEventbriteFee = false, int minTicketOrder = 1, int maxTicketOrder = 1)
        {
            var url = "https://www.eventbrite.com/json/ticket_new";
            var parms = new Dictionary<string, string>();
            parms.Add("event_id", eventId);
            parms.Add("is_donation", freeEventWithDonation?"1":"0");
            parms.Add("name", ticketName);
            parms.Add("description", description);
            parms.Add("price", String.Format("{0:n2}",  price));
            parms.Add("quantity", numberOfTickets.ToString());
            parms.Add("start_sales", String.Format("{0:yyyy-MM-dd HH:nn:ss}", startOfSales));
            parms.Add("end_sales", String.Format("{0:yyyy-MM-dd HH:nn:ss}", endOfSales));
            parms.Add("include_fee", showEventbriteFee ? "1" : "0");
            parms.Add("min", minTicketOrder.ToString());
            parms.Add("max", maxTicketOrder.ToString());
            return await httpGetForString(url, parms);
        }
        public async Task<String> UpdateTicket(string ticketTypeId, string ticketName = "", string description="", 
                                                float? price=null, int? numberOfTickets=null, DateTime? startOfSales=null, DateTime? endOfSales=null, 
                                                bool? freeEventWithDonation = null, bool? showEventbriteFee = null, 
                                                int? minTicketOrder = null, int? maxTicketOrder = null, bool? hideTicketTypeId = null)
        {
            var url = "https://www.eventbrite.com/json/ticket_update";
            var parms = new Dictionary<string, string>();
            parms.Add("id", ticketTypeId);
            if(freeEventWithDonation.HasValue)
                parms.Add("is_donation", freeEventWithDonation.Value ? "1" : "0");
            
            if(String.IsNullOrEmpty(ticketName))
                parms.Add("name", ticketName);
            if (String.IsNullOrEmpty(description)) 
                parms.Add("description", description);
            if(price.HasValue)
                parms.Add("price", String.Format("{0:n2}", price.Value));
            if(numberOfTickets.HasValue)
                parms.Add("quantity", numberOfTickets.Value.ToString());
            if(startOfSales.HasValue)
                parms.Add("start_sales", String.Format("{0:yyyy-MM-dd HH:nn:ss}", startOfSales.Value));
            if (startOfSales.HasValue) 
                parms.Add("end_sales", String.Format("{0:yyyy-MM-dd HH:nn:ss}", endOfSales.Value));
            if(showEventbriteFee.HasValue)
                parms.Add("include_fee", showEventbriteFee.Value ? "1" : "0");
            if (minTicketOrder.HasValue) 
                parms.Add("min", minTicketOrder.Value.ToString());
            if (maxTicketOrder.HasValue) 
                parms.Add("max", maxTicketOrder.Value.ToString());
            if (hideTicketTypeId.HasValue) 
                parms.Add("hide", hideTicketTypeId.Value ? "n" : "y");
            return await httpGetForString(url, parms);
        }
        #endregion
        #region Venues
        public async Task<String> NewVenue(string organizerId, string venueName, string address = "", string address2 = "", string city = "", string region = "", string postalCode = "", string countryCode = "")
        {
            var url = "https://www.eventbrite.com/json/venue_new";
            var parms = new Dictionary<string, string>();
            parms.Add("organizer_id", organizerId);
            parms.Add("name", venueName);
            if(!string.IsNullOrEmpty(address))
                parms.Add("address", address);
            if (!string.IsNullOrEmpty(address2))
                parms.Add("address_2", address2);
            if (!string.IsNullOrEmpty(city))
                parms.Add("city", city);
            if (!string.IsNullOrEmpty(region))
                parms.Add("region", region);
            if (!string.IsNullOrEmpty(postalCode))
                parms.Add("postal_code", postalCode);
            if (!string.IsNullOrEmpty(countryCode))
                parms.Add("country_code", countryCode);
            return await httpGetForString(url, parms);
        }
        public async Task<String> UpdateVenue(string venueId, string venueName="", string address = "", string address2 = "", string city = "", string region = "", string postalCode = "", string countryCode = "")
        {
            var url = "https://www.eventbrite.com/json/venue_new";
            var parms = new Dictionary<string, string>();
            parms.Add("id", venueId);
            if (!string.IsNullOrEmpty(venueName))
                parms.Add("name", venueName);
            if (!string.IsNullOrEmpty(address))
                parms.Add("address", address);
            if (!string.IsNullOrEmpty(address2))
                parms.Add("address_2", address2);
            if (!string.IsNullOrEmpty(city))
                parms.Add("city", city);
            if (!string.IsNullOrEmpty(region))
                parms.Add("region", region);
            if (!string.IsNullOrEmpty(postalCode))
                parms.Add("postal_code", postalCode);
            if (!string.IsNullOrEmpty(countryCode))
                parms.Add("country_code", countryCode);
            return await httpGetForString(url, parms);
        }
        #endregion
        #region Discount Codes
        public async Task<String> NewDiscount(string eventId, string code, DateTime startDate, DateTime endDate, float amountOff = 0.00f, float percentOff = 0.00f, string[] ticketIds = null, int? maxAvailable = null)
        {
            var url = "https://www.eventbrite.com/json/discount_new";
            var parms = new Dictionary<string, string>();
            parms.Add("event_id", eventId);
            parms.Add("code", code);
            parms.Add("amount_off", String.Format("{0:n2}", amountOff));
            parms.Add("percent_off", String.Format("{0:n2}", percentOff));
            if(ticketIds != null && ticketIds.Length>0)
                parms.Add("tickets", String.Join(",", ticketIds.Select(i=>i.Trim()).ToArray()));

            if (maxAvailable.HasValue)
                parms.Add("quantity_available", maxAvailable.Value.ToString());

            parms.Add("start_date", String.Format("{0:yyyy-MM-dd HH:nn:ss}", startDate));
            parms.Add("end_date", String.Format("{0:yyyy-MM-dd HH:nn:ss}", endDate));

            return await httpGetForString(url, parms);
        }
        public async Task<String> UpdateDiscount(string eventId, string code, DateTime startDate, DateTime endDate, float amountOff = 0.00f, float percentOff = 0.00f, string[] ticketIds = null, int? maxAvailable = null)
        {
            var url = "https://www.eventbrite.com/json/discount_update";
            var parms = new Dictionary<string, string>();
            parms.Add("event_id", eventId);
            parms.Add("code", code);
            parms.Add("amount_off", String.Format("{0:n2}", amountOff));
            parms.Add("percent_off", String.Format("{0:n2}", percentOff));
            if (ticketIds != null && ticketIds.Length > 0)
                parms.Add("tickets", String.Join(",", ticketIds.Select(i => i.Trim()).ToArray()));

            if (maxAvailable.HasValue)
                parms.Add("quantity_available", maxAvailable.Value.ToString());

            parms.Add("start_date", String.Format("{0:yyyy-MM-dd HH:nn:ss}", startDate));
            parms.Add("end_date", String.Format("{0:yyyy-MM-dd HH:nn:ss}", endDate));

            return await httpGetForString(url, parms);
        }
        public async Task<String> ListDiscountsForEvent(string eventId)
        {
            var url = "https://www.eventbrite.com/json/event_list_discounts";
            var parms = new Dictionary<string, string>();
            parms.Add("id", eventId);

            return await httpGetForString(url, parms);
        }
        #endregion
    }
}
